<template>
  <div
    id="webchatContentBox"
    class="webchatContentBox"
    v-on:scroll="queryHistoryScroll($event)"
  >
    <div class="chatMsgBox">
      <div class="historyBtn" v-show="webchatInfo.showHistoryBtn && loadFlag">
        <span class="more" @click.stop="queryMessageHistory"
          >查看历史会话消息</span
        >
      </div>
      <div class="history_liading" v-show="loadFlag === false">
        <div class="history_liading_text">
          <img src="../../assets/img/webchatLoading.gif" alt="" /><span
            >加载中</span
          >
        </div>
      </div>
      <div
        v-for="(item, index) in messageList"
        :key="index"
        class="chatMsgItem"
        :id="'msg' + index"
      >
        <webchatMsgItem
          @previewImg="previewImg"
          @withdrawFun="withdrawFun"
          :importType="importType"
          :sessionId="webchatInfo._id"
          :messageList="messageList"
          :chatMsg="item"
          :imageUrls="imageUrls"
          :chatMsgIndex="index"
          :common="common"
        >
        </webchatMsgItem>
      </div>
      <div
        class="chatMsgItem clearfix"
        v-show="isShowPreLoaded"
        v-if="common.globalConfig.isVisitorTypeNotice"
      >
        <div class="clearfix">
          <img
            :src="preLoadedInfo.visitorHeadImg"
            alt=""
            class="fl visitorsHeadImg"
            v-if="preLoadedInfo && preLoadedInfo.visitorHeadImg"
          />
          <img
            src="../../assets/img/visitorsHeadImg.png"
            alt=""
            class="fl visitorsHeadImg"
            v-else
          />
          <div class="visitorName fl">访客正在输入...</div>
        </div>
        <div
          class="preloadedMsg fl"
          v-if="preLoadedInfo && preLoadedInfo.content"
        >
          {{ preLoadedInfo.content }}
        </div>
      </div>
    </div>
  </div>
</template>
<script lang="ts">
import { Component, Vue, Prop, Watch } from 'vue-property-decorator'
import webchatMsgItem from '@/views/webchat/webchatMsgItem.vue'
import { deepClone, filterXSS } from '@/utils/common'
import { WebchatModule } from '@/store/modules/webchat'
import { CommonModule } from '@/store/modules/common'
import { msgConvertion } from '@/utils/webchat'
import { ScrollObj, MessageObj, ImgObj } from '@/views/webchat/webchatInterface'
import webchatErrcode from '@/utils/wechatErrcode'
@Component({
  name: 'webchatHead',
  components: { webchatMsgItem }
})
export default class WebchatHead extends Vue {
  @Prop() private webchatInfo
  @Prop() private importType // 哪个模块引用
  @Prop() private type // 哪个模块引用
  @Prop() private moduleType // 哪个模块引用
  @Prop({ default: '' }) private chatType // 哪个模块引用
  private $store: any
  private $route: any
  private $bus: any

  private common = { // 座席公共数据
    doMain: '',
    userId: '',
    imDoMain: '',
    globalConfig: {},
    webchatErrorCode: {}
  }

  private loadFlag = true // 加载历史flag

  private currentImgUrl = '' // 当前选中的图片地址

  private msgBoxScrollTarget: any = -1 // 滚动行为目标值

  get tabType () {
    return this.$route.path.split('/')[3]
  }

  get imageUrls () { // 聊天记录中的图片地址数组
    const list: any = this.messageList || []
    const images = list.length > 0 && list.filter((item: any) => { // 过滤出图片类型的消息
      return item.contentType === 'image'
    })
    let urls: any = []
    if (images) {
      images.forEach((item2: any) => {
        urls.push(item2.content)
      })
    }
    const nowIndex = urls.findIndex(photo => photo === this.currentImgUrl) // 找到当前图片的index
    if (nowIndex > -1) {
      const start = urls.slice(0, nowIndex)
      const end = urls.slice(nowIndex)
      urls = [...end, ...start]
    }
    return urls
  }

  get comeMsg () { // 获取当前会话新消息变化时
    return WebchatModule.webchatTodoMessageChange[this.$route.path.split('/')[4]] || 0
  }

  get isShowPreLoaded () { // 获取是否展示访客预输入
    if (this.tabType === 'webchat_todo' && WebchatModule.webchatPreLoadedObj[this.$route.path.split('/')[4]]) {
      return WebchatModule.webchatPreLoadedObj[this.$route.path.split('/')[4]].isShowPreLoaded
    } else {
      return false
    }
  }

  get preLoadedInfo () { // 获取访客预输入内容
    if (this.tabType === 'webchat_todo' && WebchatModule.webchatPreLoadedObj[this.$route.path.split('/')[4]]) {
      return WebchatModule.webchatPreLoadedObj[this.$route.path.split('/')[4]].preLoadedInfo
    } else {
      return {}
    }
  }

  get messageList () { // 获取当前会话的消息列表
    this.loadFlag = false
    const type = this.chatType || this.$route.path.split('/')[3] || this.type
    const moduleType = this.moduleType
    let messageList = []
    const initConfig = (this as any).$store.state.common.initConfig
    const reg = /(http|https):\/\/([\w.]+\/?)\S*/
    if (['webchat_todo', 'webchat_session', 'webchat_leaveMessage', 'webchat_close', 'webchat_queue'].includes(type)) {
      if (WebchatModule.webchatMessage.webchat_todo[this.$route.path.split('/')[4]] && type === 'webchat_todo') { // 待处理
        messageList = deepClone(WebchatModule.webchatMessage.webchat_todo[this.$route.path.split('/')[4]])
      } else if (type === 'webchat_session' && WebchatModule.webchatMessage.webchatDateCenter[this.webchatInfo._id]) { // 数据中心
        messageList = deepClone(WebchatModule.webchatMessage.webchatDateCenter[this.webchatInfo._id])
      } else if (type === 'webchat_leaveMessage' && WebchatModule.webchatMessage.webchat_leaveMessage[this.webchatInfo._id]) { // 留言
        messageList = deepClone(WebchatModule.webchatMessage.webchat_leaveMessage[this.webchatInfo._id])
      } else if (type === 'webchat_close' && WebchatModule.webchatMessage.webchat_close[this.$route.path.split('/')[4]]) { // 已关闭
        messageList = deepClone(WebchatModule.webchatMessage.webchat_close[this.webchatInfo._id]) || []
      } else if (type === 'webchat_queue' && WebchatModule.webchatMessage.webchat_queue[this.$route.path.split('/')[4]]) { // 排队
        messageList = deepClone(WebchatModule.webchatMessage.webchat_queue[this.webchatInfo._id]) || []
      } else {
        messageList = []
      }
      messageList.forEach((obj: MessageObj) => {
        if (obj.content.indexOf('&lt;7moorbr/&gt;') > -1 || obj.content.indexOf('<7moorbr/>') > -1) {
          obj.content = obj.content.replace(/<7moorbr\/>/g, '<br />')
          obj.content = obj.content.replace(/&lt;7moorbr\/&gt;/g, '<br />')
        }
        if (['webchat_todo', 'webchat_session', 'webchat_leaveMessage', 'webchat_close', 'webchat_queue', 'quality_score'].includes(type)) {
          const wordsSetting: any = this.$store.state.common.publicCache.globalConfig[0] || {}
          if (obj.type === 'in') {
            if (wordsSetting) {
              let visitorSensitiveWords = []
              let visitorFocusWords = []
              // 访客敏感词是否开启，是否有敏感词
              if (wordsSetting.visitorSensitiveWordsFlag && wordsSetting.visitorSensitiveWords) {
                visitorSensitiveWords = wordsSetting.visitorSensitiveWords.split(',')
              }
              // 判断访客关键词是否开启，是否有关键词
              if (wordsSetting.visitorFocusWordsFlag && wordsSetting.visitorFocusWords) {
                visitorFocusWords = wordsSetting.visitorFocusWords.split(',')
              }
              if (visitorSensitiveWords && visitorSensitiveWords.length > 0 && moduleType !== 'quality_score') {
                for (let i = 0; i < visitorSensitiveWords.length; i++) {
                  const replaceString = '**'
                  obj.contentNew = obj.content
                  obj.content = obj.content.replace(RegExp(visitorSensitiveWords[i], 'g'), replaceString);
                }
              }
              let result = true
              if (visitorSensitiveWords && visitorSensitiveWords.length > 0 && moduleType === 'quality_score') {
                for (let i = 0; i < visitorSensitiveWords.length; i++) {
                  if (obj.content.indexOf(visitorSensitiveWords[i]) !== -1) {
                    result = false
                    break
                  }
                }
              }
              if (result) {
                if (visitorFocusWords && visitorFocusWords.length > 0) {
                  for (let i = 0; i < visitorFocusWords.length; i++) {
                    const replaceString = '<span style="color: ' + wordsSetting.visitorFocusWordsColor + ';">' + visitorFocusWords[i] + '</span>'
                    obj.content = obj.content.replace(RegExp(visitorFocusWords[i], 'g'), replaceString);
                  }
                }
              }
            }
          }
          if (obj.type === 'out') {
            if (wordsSetting) {
              let agentSensitiveWords = []
              let agentFocusWords = []
              // 座席敏感词是否开启，是否有敏感词
              if (wordsSetting.agentSensitiveWordsFlag && wordsSetting.agentSensitiveWords) {
                agentSensitiveWords = wordsSetting.agentSensitiveWords.split(',')
              }
              // 座席关键词是否开启，是否有关键词
              if (wordsSetting.agentFocusWordsFlag && wordsSetting.agentFocusWords) {
                agentFocusWords = wordsSetting.agentFocusWords.split(',')
              }
              let result = true
              if (agentSensitiveWords && agentSensitiveWords.length > 0 && moduleType !== 'quality_score') {
                for (let i = 0; i < agentSensitiveWords.length; i++) {
                  obj.contentNew = obj.content
                  const replaceString = '**'
                  obj.content = obj.content.replace(RegExp(agentSensitiveWords[i], 'g'), replaceString);
                }
              }
              if (agentSensitiveWords && agentSensitiveWords.length > 0 && moduleType === 'quality_score') {
                for (let i = 0; i < agentSensitiveWords.length; i++) {
                  if (obj.content.indexOf(agentSensitiveWords[i]) !== -1) {
                    // 当当前内容有敏感词时不做关键词高亮了
                    result = false
                    break
                  }
                }
              }
              if (result) {
                if (agentFocusWords && agentFocusWords.length > 0) {
                  for (let i = 0; i < agentFocusWords.length; i++) {
                    const replaceString = '<span style="color: ' + wordsSetting.agentFocusWordsColor + ';">' + agentFocusWords[i] + '</span>'
                    obj.content = obj.content.replace(RegExp(agentFocusWords[i], 'g'), replaceString);
                  }
                }
              }
            }
          }
        }
        const timeNow = new Date().getTime()
        const user = this.$store.state.common.session.user._id
        const msgTimestamp: any = obj.createTimestamp || obj.timeStamp
        if (msgTimestamp && timeNow - msgTimestamp < 180000 && ['pc', 'wap', 'sdk', 'wxsdk'].includes(obj.platform) &&
          obj.type === 'out' && this.tabType === 'webchat_todo' && user === obj.userId) {
          this.$set(obj, 'tipDisabled', true)
        } else {
          this.$set(obj, 'tipDisabled', false)
        }
        // 会话消息，回显的时候，回车没有替换成br处理
        obj.content = obj.content.replace(/[\n\r]/g, '<br />')
        obj.content = filterXSS(obj.content)
        if (obj.contentType === 'image' || obj.contentType === 'file') { // 图片和文件域名拼接
          if (!reg.test(obj.content)) {
            obj.content = initConfig ? initConfig.qiniuDomainMap.im + obj.content : ''
          }
        }
        if (obj.contentType === 'orderCardInfo' && obj.content) { // 订单消息处理
          try {
            obj.content = JSON.parse(decodeURIComponent(obj.content))
          } catch (e) {
            obj.content = JSON.parse(obj.content) || {}
          }
        }
        const searchKey = WebchatModule.messageKeyWords || []
        if (this.importType === 'dataCenter' &&
          searchKey.length > 0 &&
          obj.contentType === 'text' &&
          obj.type === 'in' &&
          obj.content) { // 高级搜索中带内容搜索
          searchKey.forEach(keyItem => {
            if (obj.content.indexOf(keyItem) > -1) {
              obj.isSearchKey = true
            }
          })
        }
        // (text为文本消息，newPushQues 为机器人分组消息, msgTask 为机器人物流消息)
        if (obj.contentType === 'text' || obj.contentType === 'newPushQues' || obj.contentType === 'msgTask') { // 文本消息和机器人分组和机器人物流节点需要处理超链接和表情
          obj.realContent = deepClone(obj.content)
          obj.content = msgConvertion(obj.content)
        }
      })
      this.$nextTick(() => {
        this.loadFlag = true
      })
      return messageList
    }
  }

  private previewImg (item: ImgObj) { // 查看当前图片
    this.currentImgUrl = item.content
  }

  public scrollToBottom (data: ScrollObj) { // 滚动条到最下方
    this.$nextTick(() => {
      if (document.getElementsByClassName(data.scrollName).length) {
        document.getElementsByClassName(data.scrollName)[0].scrollTop = document.getElementsByClassName(data.warpName)[0].scrollHeight + 16
      }
    })
  }

  private queryHistoryScroll (event: any) { // 滚动加载历史记录
    if (event.target.scrollTop < 2 && this.webchatInfo.showHistoryBtn && this.loadFlag) {
      this.loadFlag = false
      const chatMsgBoxDom: any = document.getElementsByClassName('chatMsgBox')[0]
      this.msgBoxScrollTarget = chatMsgBoxDom.offsetHeight // 获取当前滚动条位置
      if (this.messageList && this.messageList.length) {
        this.queryMessageHistory({ type: 'scroll' })
      } else {
        this.loadFlag = true
      }
    }
    this.onScroll(event);
  }

  // 消息提示框逻辑

  private onScroll (event: any) {
    // 距离底部高度
    const scrollBottom =
      event.target.scrollHeight -
      event.target.scrollTop -
      event.target.clientHeight;
    WebchatModule.SET_MSG_BOX_SCROLL_BOTTOM(parseInt(scrollBottom.toString(), 10));
    // 未读消息距离顶部的距离
    if (WebchatModule.unreadmessagesid) {
      console.log(WebchatModule.unreadmessagesid)
      const box: any = document.getElementById(WebchatModule.unreadmessagesid)
      const boxTop = box.getBoundingClientRect().top
      // 消息框距离顶部的距离
      const messageBox: any = document.getElementById('webchatContentBox')
      const messageBoxTop = messageBox.getBoundingClientRect().top
      const messageBoxHeight = messageBox.getBoundingClientRect().height
      const distance = boxTop - messageBoxTop - messageBoxHeight
      WebchatModule.EMPTY_UNREAD_MESSAGE_DISTANCE(distance)
    }
  }

  private queryMessageHistory ({ type }) { // 加载历史数据
    this.loadFlag = false
    const chatMsgBoxDom: any = document.getElementsByClassName('chatMsgBox')[0]
    this.msgBoxScrollTarget = chatMsgBoxDom.offsetHeight // 获取当前滚动条位置
    const { visitorId, _id } = this.webchatInfo
    const messageHistoryList: any = deepClone(this.messageList)
    let dateTime = 0
    if (messageHistoryList && messageHistoryList.length > 0) { // 拿最后一条消息的创建时间去查历史消息
      dateTime = messageHistoryList[0].createTimestamp
    }
    let webchatType = this.$route.path.split('/')[3] === 'webchat_session' ? 'webchatDateCenter' : this.$route.path.split('/')[3]
    if (this.chatType) {
      webchatType = this.chatType === 'webchat_session' ? 'webchatDateCenter' : this.chatType;
    }
    // {visitorId(访客id)，dateTime(当前时间戳)，limit(查询当前历史消息条数)，_id(会话id)，isNewSession(是否是新会话接入)}
    const messageHistoryData: any = { visitorId, dateTime, limit: 20, _id, isNewSession: false, webchatType } // 获取消息历史参数
    if (type === 'scroll') { // 滚动加载50条数据
      messageHistoryData.limit = 50
    }
    if (this.importType === 'dataCenter') { // 数据中心引用此组件需要增加当前会话id去查询当前会话的聊天内容
      messageHistoryData.sessionId = _id
    }
    const messageHistoryActionData = { url: '/im-center/action/webchat/queryHistory', method: 'POST', data: messageHistoryData }
    WebchatModule.queryWebchatHistory(messageHistoryActionData).then(resp => {
      if (resp) {
        // 保留当前滚动条位置
        window.setTimeout(() => {
          if (this.msgBoxScrollTarget > -1 && document.getElementsByClassName('webchatContentBox').length > 0) {
            this.$nextTick(() => {
              document.getElementsByClassName('webchatContentBox')[0].scrollTop = chatMsgBoxDom.scrollHeight - this.msgBoxScrollTarget - 40
              this.msgBoxScrollTarget = -1
            })
          }
          this.loadFlag = true
        }, 0)
      }
    })
  }

  private activated () {
    // 切换模块之后，模块被重新激活，页面滚动到底部
    if (document.getElementsByClassName('webchatContentBox').length > 0 && document.getElementsByClassName('chatMsgBox').length > 0) {
      this.scrollToBottom({ scrollName: 'webchatContentBox', warpName: 'chatMsgBox' })
    }
  }

  private dealMsg () { // 处理消息消费
    if (this.messageList && this.webchatInfo) {
      const unReadMessageList: any = []
      this.messageList.forEach((item: any) => {
        if (item.type === 'in' && !item.dealCustomerMsg) { // 如果是访客消息并且没被消费得去消费
          unReadMessageList.push(item.messageId || item._id)
        }
      })
      if (unReadMessageList.length > 0 && this.webchatInfo.visitorId && this.webchatInfo.accessId) {
        const sendData = {
          visitorId: this.webchatInfo.visitorId, // 访客id
          accessId: this.webchatInfo.accessId, // 接入号id
          sessionId: this.$route.path.split('/')[4], // 会话id
          messageIdList: unReadMessageList, // 需要消费的消息id
          platform: this.webchatInfo.platform // 来源渠道
        }
        const actionData = { url: '/im-center/action/webchat/dealImMsg', method: 'POST', data: sendData }
        WebchatModule.dealMsg(actionData)
      }
    }
  }

  private withdrawFun (chatMsg: any) { // 消息撤回
    const { messageId, visitorId, _id } = chatMsg
    const sendData = {
      messageId: messageId || _id,
      visitorId
    }
    const actionData = { url: '/im-center/action/webchat/withdrawMessage', method: 'POST', data: sendData }
    WebchatModule.webchatCommonAction(actionData).then(res => {
      if (res) {
        WebchatModule.WITHDRAW_MSG(chatMsg)
      }
    })
  }

  @Watch('comeMsg') // 监听新消息变化
  private comeMsgChange (newval: number, old: number) {
    if (newval === old) {
      return false
    }
    const route = this.$route.path.split('/')[3]
    if (route === 'webchat_todo') { // 在待处理时去处理
      const messageList = deepClone(this.messageList)
      const lastNewMsg: any = messageList[messageList.length - 1]
      if (lastNewMsg && !document.hidden && lastNewMsg.eventType === 'newMsg' && !lastNewMsg.dealCustomerMsg && lastNewMsg.type === 'in') { // 处理未读消息数
        this.dealMsg()
      }
      this.$nextTick(() => {
        const currentScrollBottom = WebchatModule.msgBoxScrollBottom;
        if (currentScrollBottom <= 70) {
          this.scrollToBottom({ scrollName: 'webchatContentBox', warpName: 'chatMsgBox' })
        }
      })
    }
  }

  private handleWinFocus () { // 窗口聚焦事件
    const currentRoute = this.$route.path.split('/')
    if (currentRoute && currentRoute.indexOf('webchat_todo') > -1) { // 在待处理列表去调用消费事件
      this.dealMsg()
    }
  }

  private getWebchatError () { // 获取小程序， 微信错误码
    // 只有微信，小程序渠道并且之前没有取过错误码在去请求
    const errorObj = this.$store.state.webchat.webchatErrorCode
    if (['weixin', 'wxmini', 'wxkf'].includes(this.webchatInfo.platform) && Object.keys(errorObj).length === 0) {
      const code = webchatErrcode
      this.common.webchatErrorCode = code
      WebchatModule.SET_WEBCHAT_ERROR(code)
    }
  }

  private initData () {
    this.dealMsg()
    this.$nextTick(() => {
      this.scrollToBottom({ scrollName: 'webchatContentBox', warpName: 'chatMsgBox' })
    })
    this.getWebchatError() // 在线工作台在此获取小程序，微信错误码
  }

  private mounted () {
    this.$bus.$on('renderWebchatSummary', () => {
      this.initData()
      this.common.globalConfig = this.$store.state.common.publicCache.globalConfig[0] || {}
    })
    const initConfig = this.$store.state.common.initConfig
    const user = this.$store.state.common.session.user
    const doMain = initConfig && initConfig.qiniuDomainMap ? initConfig.qiniuDomainMap.common : '' // 公共域名
    const imDoMain = initConfig && initConfig.qiniuDomainMap ? initConfig.qiniuDomainMap.im : '' // 公共域名
    this.common.imDoMain = imDoMain
    this.common.doMain = doMain + '/'
    this.common.userId = user && user._id ? user._id : '' // 此座席id
    window.addEventListener('focus', this.handleWinFocus) // 监听窗口聚焦
    if (this.importType === 'dataCenter') { // 数据中心在此获取小程序，微信错误码
      this.getWebchatError()
    }
  }

  private beforeDestroy () {
    window.removeEventListener('focus', this.handleWinFocus) // 销毁窗口聚焦
    this.$bus.$off('renderWebchatSummary')
  }
}
</script>
<style lang="stylus" scoped>
>>> #webchatContentBox
  position relative
.webchatContentBox
  height calc(100% - 216px)
  overflow-y auto
  padding 0px 16px
  margin-bottom 10px
  color #BABECB
  position relative
  .historyBtn
    text-align center
    margin 16px 0px 19px 0px
    .more
      color #008BEE
      cursor pointer
  .chatMsgItem
    margin 20px 0px
  .visitorsHeadImg
    width 36px
    height 36px
    border-radius 50%
  .visitorName
    color #767E91
    margin 0px 5px
  .preloadedMsg
    margin-top -20px
    margin-left 40px
    max-width calc(100% - 200px)
    line-height 22px
    padding 10px
    color #303753
    word-break break-word
    white-space normal
    background-color #ffffff
    border-radius 10px
    border 1px solid #E7E9ED
  .history_liading
    margin-top 5px
    text-align center
    .history_liading_text
      color #000
      display inline-block
      &:after
        display inline-block
        width 0
        height 100%
        content 'center'
        vertical-align middle
        overflow hidden
      img
        vertical-align middle
</style>
